#include "EngineStuff.h"
#include "InputLayouts.h"
#include "RenderTarget.h"

///Statics
ID3D11Device*					EngineStuff::EGraphicsDevice; 	
ID3D11DeviceContext*			EngineStuff::EImediateDeviceContext;
InputManager*					EngineStuff::EInputManager;
AssetManagment*					EngineStuff::EAssetManagment;
int								EngineStuff::g_WindowWidth;
int								EngineStuff::g_WindowHeight;	

stack<DepthStencilState>		EngineStuff::DepthStencilStates;
stack<ID3D11RasterizerState*>	EngineStuff::RasterizerStates;
stack<BlendState>				EngineStuff::BlendStates;
stack<RenderTarget*>			EngineStuff::RenderTargets;
	


EngineStuff::EngineStuff(void)
{
	ClearColor[0] =  0.0f;
	ClearColor[0] =  0.125f; 
	ClearColor[0] =  0.3f;
	ClearColor[0] =  1.0f;	
}

EngineStuff::~EngineStuff(void)
{

}

void EngineStuff::Cleanup()
{
	InputLayouts::Unload();	
	EInputManager->Shutdown();
	delete EAssetManagment;
	delete screenManager;
	delete EInputManager;

	
	while(DepthStencilStates.size() != 0)
	{
		DepthStencilState ds = DepthStencilStates.top();
		ds.State->Release();
		DepthStencilStates.pop();
	}

	while(RasterizerStates.size() != 0)
	{
		ID3D11RasterizerState* ds = RasterizerStates.top();
		ds->Release();
		RasterizerStates.pop();
	}	

	while(BlendStates.size() != 0)
	{
		BlendState ds = BlendStates.top();
		ds.State->Release();
		delete ds.BlendFactor;
		BlendStates.pop();
	}		
	
	while(RenderTargets.size() != 0)
	{
		RenderTarget* ds = RenderTargets.top();
		delete ds;		
		RenderTargets.pop();
	}	
	



#ifdef _DEBUG
	ID3D11Debug* d3dDebug = NULL;
	EGraphicsDevice->QueryInterface( IID_ID3D11Debug, (VOID**)(&d3dDebug) );
	d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
	d3dDebug->Release();
#endif

	g_pSwapChain->Release();
	EGraphicsDevice->Release(); 			
	EImediateDeviceContext->Release();
	
}

void EngineStuff::InitEngine(const char* appName, HINSTANCE HInstance ,int width, int height, bool FullScreen, bool VsyncEnabled,D3D_FEATURE_LEVEL featureLevel , D3D_DRIVER_TYPE driverType , AntiAliasingSettings set )
{
	hInstance  = HInstance;
	g_WindowWidth = width;
	g_WindowHeight = height;
	fullscreen = FullScreen;
	m_vsync_enabled = VsyncEnabled;
	screenManager = new ScreenManager(this);	
	InitWindow(appName);	
	assert(InitDirectX11(featureLevel,driverType,set) == S_OK);
	EInputManager = new InputManager();
	EAssetManagment = new AssetManagment();	
	assert(EInputManager->Initialize(hInstance,hWnd,g_WindowWidth,g_WindowHeight));
	InputLayouts::LoadLayouts();
	elapsedTime = timeGetTime() ;		
}

HRESULT EngineStuff::RecreateDevice(UINT width, UINT height, D3D_FEATURE_LEVEL featureLevel , D3D_DRIVER_TYPE driverType , AntiAliasingSettings set )
{
	HRESULT result;
	g_WindowWidth = width;
	g_WindowHeight = height;
	set = CheckMultSample(set);

	DXGI_SWAP_CHAIN_DESC swapChainDesc;
	ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));	
	swapChainDesc.BufferCount = 1;
	swapChainDesc.BufferDesc.Width = g_WindowWidth;
	swapChainDesc.BufferDesc.Height = g_WindowHeight;	
	swapChainDesc.BufferDesc.Format = set.surfaceFormat;               
	if(m_vsync_enabled)
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;
	}
	else
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
	}

	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;	
	swapChainDesc.OutputWindow = hWnd;
	swapChainDesc.SampleDesc.Count = set.sampleCount;
	swapChainDesc.SampleDesc.Quality = set.sampleQuality;
	
	if(fullscreen)
	{
		swapChainDesc.Windowed = false;
	}
	else
	{
		swapChainDesc.Windowed = true;
	}	
	swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;	
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;	
	swapChainDesc.Flags = 0;    	

	IDXGIDevice * pDXGIDevice;
	result = EGraphicsDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
	CheckError(result);	
	      
	IDXGIAdapter * pDXGIAdapter;
	result = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
	CheckError(result);	

	IDXGIFactory * pIDXGIFactory;
	result = pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);
	CheckError(result);	

	g_pSwapChain->Release();
	result = pIDXGIFactory->CreateSwapChain(EGraphicsDevice,&swapChainDesc,&g_pSwapChain);
	CheckError(result);	

	pIDXGIFactory->Release();	

	ID3D11Texture2D* pBuffer;
    result = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBuffer);
	CheckError(result);
	
	ID3D11Texture2D* g_pDepthStencil = NULL;

	// Create depth stencil texture
    D3D11_TEXTURE2D_DESC descDepth;
    descDepth.Width = g_WindowWidth;
	descDepth.Height = g_WindowHeight;
    descDepth.MipLevels = 1;
    descDepth.ArraySize = 1;
    descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	descDepth.SampleDesc.Count = set.sampleCount;
	descDepth.SampleDesc.Quality = set.sampleQuality;
    descDepth.Usage = D3D11_USAGE_DEFAULT;
    descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    descDepth.CPUAccessFlags = 0;
    descDepth.MiscFlags = 0;	

	result = EGraphicsDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil);
	CheckError(result);
	
    // Create the depth stencil view
    D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
	ZeroMemory(&descDSV, sizeof(descDSV));
    descDSV.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	if(set.multSampleEnable)		
		descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
	else
		descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    descDSV.Texture2D.MipSlice = 0;

    result = EGraphicsDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView );
    CheckError(result);	
	
    result = EGraphicsDevice->CreateRenderTargetView(pBuffer, NULL, &g_pSCRenderTargetView );
	CheckError(result);

	RenderTarget* rt = new RenderTarget(g_pSCRenderTargetView,g_pDepthStencilView);
	PushRenderTarget(rt);    

    pBuffer->Release();		

	D3D11_RASTERIZER_DESC oldState;
	g_pRasterState->GetDesc(&oldState);	
	oldState.MultisampleEnable = set.multSampleEnable;
    
    EGraphicsDevice->CreateRasterizerState( &oldState, &g_pRasterState );	    
	PushRasterState(g_pRasterState );	

	return result;
}

void EngineStuff::EnterOnLoop()
{
	MessageLoop();
}

HRESULT EngineStuff::InitDirectX11(D3D_FEATURE_LEVEL featureLevel,D3D_DRIVER_TYPE driverType,AntiAliasingSettings set )
{
	HRESULT result = S_OK;    
    
    // iterate through the candidate adapters
    IDXGIFactory *pFactory;
	IDXGIAdapter* adapter;
	IDXGIOutput* adapterOutput;
	
    result  = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pFactory) );	
	CheckError(result);	

	result  = pFactory->MakeWindowAssociation(hWnd,0);
	CheckError(result);	

	// Use the factory to create an adapter for the primary graphics interface (video card).
	result = pFactory->EnumAdapters(0, &adapter);
	CheckError(result);


	// Enumerate the primary adapter output (monitor).
	result = adapter->EnumOutputs(0, &adapterOutput);
	CheckError(result);	

	UINT numModes;

	// Get the number of modes that fit the format display format for the adapter output (monitor).
	result = adapterOutput->GetDisplayModeList(set.surfaceFormat, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
	CheckError(result);

	// Create a list to hold all the possible display modes for this monitor/video card combination.
	DXGI_MODE_DESC* displayModeList = new DXGI_MODE_DESC[numModes];	

	// Now fill the display mode list structures.
	result = adapterOutput->GetDisplayModeList(set.surfaceFormat, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);
	CheckError(result);

	// Now go through all the display modes and find the one that matches the screen width and height.
	// When a match is found store the numerator and denominator of the refresh rate for that monitor.
	for(int i=0; i<numModes; i++)
	{
		if(displayModeList[i].Width == (unsigned int)g_WindowWidth)
		{
			if(displayModeList[i].Height == (unsigned int)g_WindowHeight)
			{
				numerator = displayModeList[i].RefreshRate.Numerator;
				denominator = displayModeList[i].RefreshRate.Denominator;
			}
		}
	}

	//// Get the adapter (video card) description.
	DXGI_ADAPTER_DESC adapterDesc;
	result = adapter->GetDesc(&adapterDesc);
	CheckError(result);
	
	//// Store the dedicated video card memory in megabytes.
	//m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024);

	//// Convert the name of the video card to a character array and store it.
	//wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);	

	SAFE_DELETE_ARRAY(displayModeList);
	SAFE_RELEASE(adapterOutput);
	SAFE_RELEASE(adapter);
	SAFE_RELEASE(pFactory);
	
	DXGI_SWAP_CHAIN_DESC swapChainDesc;

	// Initialize the swap chain description.
	ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));

	// Set to a single back buffer.
	swapChainDesc.BufferCount = 1;

	// Set the width and height of the back buffer.
	swapChainDesc.BufferDesc.Width = g_WindowWidth;
	swapChainDesc.BufferDesc.Height = g_WindowHeight;

	// Set surface for the back buffer.
	swapChainDesc.BufferDesc.Format = set.surfaceFormat;
        
     // Set the refresh rate of the back buffer.
	if(m_vsync_enabled)
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;
	}
	else
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
	}

	// Set the usage of the back buffer.
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

	// Set the handle for the window to render to.
	swapChainDesc.OutputWindow = hWnd;

	// Turn multisampling off.
	swapChainDesc.SampleDesc.Count = set.sampleCount;
	swapChainDesc.SampleDesc.Quality = set.sampleQuality;

	// Set to full screen or windowed mode.
	if(fullscreen)
	{
		swapChainDesc.Windowed = false;
	}
	else
	{
		swapChainDesc.Windowed = true;
	}

	// Set the scan line ordering and scaling to unspecified.
	swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

	// Discard the back buffer contents after presenting.
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

	// Don't set the advanced flags.
	swapChainDesc.Flags = 0;    	

#ifdef _DEBUG
	result = D3D11CreateDevice(
		NULL,
		driverType, 
		NULL,D3D11_CREATE_DEVICE_DEBUG 
		,
		&featureLevel, 
		1, 
		D3D11_SDK_VERSION, 		
		&EGraphicsDevice, 
		NULL, 
		&EImediateDeviceContext);
    
	CheckError(result);
#else
	result = D3D11CreateDevice(
		NULL,
		driverType, 
		NULL,
		0,
		&featureLevel, 
		1, 
		D3D11_SDK_VERSION, 		
		&EGraphicsDevice, 
		NULL, 
		&EImediateDeviceContext);
	CheckError(result);	
#endif	

	set = CheckMultSample(set);			

	IDXGIDevice * pDXGIDevice;
	result = EGraphicsDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
	CheckError(result);	
	      
	IDXGIAdapter * pDXGIAdapter;
	result = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
	CheckError(result);		

	IDXGIFactory * pIDXGIFactory;
	result = pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);
	CheckError(result);	

	result = pIDXGIFactory->CreateSwapChain(EGraphicsDevice,&swapChainDesc,&g_pSwapChain);
	CheckError(result);	

	SAFE_RELEASE(pDXGIDevice);
	SAFE_RELEASE(pIDXGIFactory);
	SAFE_RELEASE(pDXGIAdapter);

    // Create a render target view of the swapchain
    ID3D11Texture2D* pBuffer;
    result = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBuffer);
	CheckError(result);	

	ID3D11Texture2D* g_pDepthStencil = NULL;

	// Create depth stencil texture
    D3D11_TEXTURE2D_DESC descDepth;
    descDepth.Width = g_WindowWidth;
	descDepth.Height = g_WindowHeight;
    descDepth.MipLevels = 1;
    descDepth.ArraySize = 1;
    descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	descDepth.SampleDesc.Count = set.sampleCount;
	descDepth.SampleDesc.Quality = set.sampleQuality;
    descDepth.Usage = D3D11_USAGE_DEFAULT;
    descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    descDepth.CPUAccessFlags = 0;
    descDepth.MiscFlags = 0;	

	result = EGraphicsDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil);
	CheckError(result);

	D3D11_DEPTH_STENCIL_DESC descDS;
	ZeroMemory(&descDS, sizeof(descDS));
	descDS.DepthEnable = true;
	descDS.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	descDS.DepthFunc = D3D11_COMPARISON_LESS;
	// Stencil test values
	descDS.StencilEnable = false;
	descDS.StencilReadMask = (UINT8)0xFFFFFFFF;
	descDS.StencilWriteMask = (UINT8)0xFFFFFFFF;
	// Stencil op if pixel is front
	descDS.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	descDS.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
	descDS.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	descDS.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
	// Stencil op if pixel is back
	descDS.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	descDS.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
	descDS.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	descDS.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	result = EGraphicsDevice->CreateDepthStencilState(&descDS, &g_pDepthStencilState);
	CheckError(result);

	PushDepthState(g_pDepthStencilState,1);	

    // Create the depth stencil view
    D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
	ZeroMemory(&descDSV, sizeof(descDSV));
    descDSV.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	if(set.multSampleEnable)		
		descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
	else
		descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    descDSV.Texture2D.MipSlice = 0;

    result = EGraphicsDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView );
    CheckError(result);	
	
    result = EGraphicsDevice->CreateRenderTargetView(pBuffer, NULL, &g_pSCRenderTargetView );
	CheckError(result);

    pBuffer->Release();
	
	RenderTarget* rt = new RenderTarget(g_pSCRenderTargetView,g_pDepthStencilView);
	PushRenderTarget(rt);    

    // Setup the viewport    
    ViewPort.Width = g_WindowWidth;
    ViewPort.Height = g_WindowHeight;
    ViewPort.MinDepth = 0.0f;
    ViewPort.MaxDepth = 1.0f;
    ViewPort.TopLeftX = 0;
    ViewPort.TopLeftY = 0;
    EImediateDeviceContext->RSSetViewports( 1, &ViewPort);


	D3D11_RASTERIZER_DESC rasterizerState;
    rasterizerState.FillMode = D3D11_FILL_SOLID;
	rasterizerState.CullMode = D3D11_CULL_NONE;
    rasterizerState.FrontCounterClockwise = false;
    rasterizerState.DepthBias = false;
    rasterizerState.DepthBiasClamp = 0;
    rasterizerState.SlopeScaledDepthBias = 0;
    rasterizerState.DepthClipEnable = true;
    rasterizerState.ScissorEnable = false;
	rasterizerState.MultisampleEnable = set.multSampleEnable;
    rasterizerState.AntialiasedLineEnable = false;
    EGraphicsDevice->CreateRasterizerState( &rasterizerState, &g_pRasterState );
    
	PushRasterState(g_pRasterState );	
	
	D3D11_BLEND_DESC blendDesc;
    blendDesc.AlphaToCoverageEnable = false;
    blendDesc.IndependentBlendEnable = false;    
    blendDesc.RenderTarget[0].BlendEnable = false;
    blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
    blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
    blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;    
    CheckError(EGraphicsDevice->CreateBlendState(&blendDesc, &g_pAlphaBlendState));
		
	PushBlenderState(g_pAlphaBlendState,0,0xffffffff); 	

    return S_OK;
    
}

int EngineStuff::MessageLoop()
{	            
    // Main message loop
    MSG msg = {0};
    while( WM_QUIT != msg.message )
    {
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
        {
			EInputManager->UpdateInputManager();
            RenderLoop();
        }
    }

    Cleanup();
	UnregisterClass( wClasseX.lpszClassName, wClasseX.hInstance );
    return ( int )msg.wParam;
	

}

void EngineStuff::InitWindow(const char* appName)
{
		   // Register the window class
			WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc , 0L, 0L,
							  GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
							  appName, NULL };

			wClasseX = wc;
			RegisterClassEx( &wClasseX );

			// Create the application's window
			int xBorder = ::GetSystemMetrics(SM_CXSIZEFRAME);
			int yMenu = ::GetSystemMetrics(SM_CYMENU);
			int yBorder = ::GetSystemMetrics(SM_CYSIZEFRAME);
			hWnd = CreateWindow( wc.lpszClassName, appName,
									  WS_OVERLAPPEDWINDOW, 0, 0, g_WindowWidth + 2*xBorder, g_WindowHeight+ 2*yBorder+yMenu,
									  NULL, NULL, wc.hInstance, NULL );

			assert(hWnd);
		 
			// Show the window
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

}

LRESULT  WINAPI EngineStuff::MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch( msg )
    {
        case WM_DESTROY:
        case WM_KEYDOWN:
            if (msg != WM_KEYDOWN || wParam == 27) {
                PostQuitMessage( 0 );
                return 0;
            }
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

void EngineStuff::RenderLoop(void)
{	
	EImediateDeviceContext->ClearRenderTargetView( g_pSCRenderTargetView , ClearColor );
	EImediateDeviceContext->ClearDepthStencilView( g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
	
	DWORD tp = timeGetTime() ;	
	screenManager->Update(tp - elapsedTime);
	screenManager->Draw(elapsedTime);
	elapsedTime = tp;
	
    //
    // Present our back buffer to our front buffer
    //
	g_pSwapChain->Present(0,0);

}

RenderTarget* EngineStuff::PopRenderTarget(void)
{
	if(RenderTargets.size() == 0)
	{
		return NULL;
	}
	RenderTarget* rt = RenderTargets.top();
	rt->SetOnDevice();
	RenderTargets.pop();

	return rt;
}

void EngineStuff::PushRenderTarget(RenderTarget* rt)
{
	rt->SetOnDevice();
	RenderTargets.push(rt);
		
}

AntiAliasingSettings EngineStuff::CheckMultSample(AntiAliasingSettings setting)
{	
	UINT *support = new UINT();		
	HRESULT res = EngineStuff::EGraphicsDevice->CheckFormatSupport(setting.surfaceFormat,support);
	if(FAILED(res) || (*support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != D3D11_FORMAT_SUPPORT_RENDER_TARGET)
	{
			AntiAliasingSettings a;
			a.surfaceFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
			a.multSampleEnable = false;
			return a;
	}	

	if(!setting.multSampleEnable)
	{
		return setting;
	}

	UINT* qualitys = new UINT();
	res = EngineStuff::EGraphicsDevice->CheckMultisampleQualityLevels(setting.surfaceFormat,setting.sampleCount,qualitys);
	if(FAILED(res))
	{
			AntiAliasingSettings a;
			a.surfaceFormat = setting.surfaceFormat;
			a.multSampleEnable = false;
			return a;
	}

	if(*qualitys >= setting.sampleQuality)
	{
			AntiAliasingSettings a;
			a.surfaceFormat = setting.surfaceFormat;
			a.multSampleEnable = setting.multSampleEnable;
			a.sampleCount = setting.sampleCount;  
			a.sampleQuality = setting.sampleQuality;
			return a;
	}
	else
	{
		if(*qualitys == 0)
		{
			for(int i = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i > 0 ; i -- )
			{
				EngineStuff::EGraphicsDevice->CheckMultisampleQualityLevels(setting.surfaceFormat,i,qualitys);
				if(*qualitys != 0)
				{
					AntiAliasingSettings a;
					a.surfaceFormat = setting.surfaceFormat;
					a.multSampleEnable = true;
					a.sampleCount = i;  
					a.sampleQuality = *qualitys;
					return a;
				}
			}			
		}
		else
		{
			AntiAliasingSettings a;
			a.surfaceFormat = setting.surfaceFormat;
			a.multSampleEnable = true;
			a.sampleCount = setting.sampleCount;  
			a.sampleQuality = *qualitys;
			return a;
		}
	}	

	AntiAliasingSettings a;
	a.surfaceFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
	a.multSampleEnable = false;
	return a;
}